package cn.core.sign.service.impl;

import cn.core.sign.eo.Org;
import cn.core.sign.eo.Post;
import cn.core.sign.eo.PostRole;
import cn.core.sign.mapper.OrgMapper;
import cn.core.sign.mapper.PostMapper;
import cn.core.sign.mapper.PostRoleMapper;
import cn.core.sign.qo.OrgQO;
import cn.core.sign.qo.PostQO;
import cn.core.sign.qo.PostRoleQO;
import cn.core.sign.service.intf.IPostService;
import cn.core.sign.vo.PostVO;
import cn.core.tool.event.CoreDataEvent;
import cn.core.tool.exception.CoreException;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.CoreTree;
import cn.core.tool.util.Paging;
import cn.core.tool.util.Param;
import com.google.gson.reflect.TypeToken;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;

/**
 * 岗位 服务实现
 */
@Log4j2
@Primary
@Service
public class PostServiceImpl implements IPostService {

  @Resource
  private PostMapper postMapper;

  @Resource
  private PostRoleMapper postRoleMapper;

  @Resource
  private OrgMapper orgMapper;

  @Resource
  private ApplicationEventPublisher applicationEventPublisher;

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public PostVO save(PostVO eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      eo.setId(CoreTool.getUUID32());
      Post post = new Post();
      BeanUtils.copyProperties(eo, post);
      LinkedHashSet<PostRole> postRoleSet = new LinkedHashSet<>();
      if (CoreTool.isNotEmpty(eo.getRoleList())) {
        for (String str : eo.getRoleList()) {
          postRoleSet.add(new PostRole()
              .setId(CoreTool.getUUID32())
              .setRoleId(str)
              .setPostId(post.getId()));
        }
      }
      postMapper.save(post);
      if (CoreTool.isNotEmpty(postRoleSet)) {
        postRoleMapper.saveBatch(new Paging<>(), postRoleSet);
      }
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Collection<Post> saveBatch(Collection<Post> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Post eo : eos) {
        if (CoreTool.isNullEo(eo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        eo.setId(CoreTool.getUUID32());
      }
      postMapper.saveBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public PostVO update(PostVO eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      Post oeo = postMapper.pk(new PostQO().setId(eo.getId()));
      if (CoreTool.isNullEo(oeo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
//      if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//        throw new CoreException(CoreException.E_VERSIONS_ERR);
//      }
      Post post = new Post();
      BeanUtils.copyProperties(eo, post);
      LinkedHashSet<PostRole> postRoleSet = new LinkedHashSet<>();
      if (CoreTool.isNotEmpty(eo.getRoleList())) {
        for (String str : eo.getRoleList()) {
          postRoleSet.add(new PostRole()
              .setId(CoreTool.getUUID32())
              .setRoleId(str)
              .setPostId(post.getId()));
        }
      }
      postMapper.update(post);
      if (CoreTool.isNotEmpty(postRoleSet)) {
        postRoleMapper.removeQuery(new PostRoleQO().setPostId(post.getId()));
        postRoleMapper.saveBatch(new Paging<>(), postRoleSet);
      } else {
        postRoleMapper.removeQuery(new PostRoleQO().setPostId(post.getId()));
      }
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Collection<Post> updateBatch(Collection<Post> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Post eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        Post oeo = postMapper.pk(new PostQO().setId(eo.getId()));
        if (CoreTool.isNullEo(oeo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
//        if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//          throw new CoreException(CoreException.E_VERSIONS_ERR);
//        }
      }
      postMapper.updateBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public void remove(Post eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      postMapper.remove(eo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public void removeBatch(Collection<Post> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      LinkedHashSet<String> postIdAndIn = new LinkedHashSet<>();
      for (Post eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        postIdAndIn.add(eo.getId());
      }
      if (CoreTool.isNotEmpty(postIdAndIn)) {
        postRoleMapper.removeQuery(new PostRoleQO().setPostIdAndIn(postIdAndIn));
      }
      postMapper.removeBatch(eos);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Long count(PostQO qo) throws Exception {
    try {
      return postMapper.count(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Post pk(PostQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return postMapper.pk(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Collection<Post> query(PostQO qo) throws Exception {
    try {
      return postMapper.query(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Paging<Post> paging(Param<PostQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<Post> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = postMapper.count(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(postMapper.paging(paging, null));
        }
      } else {
        Long count = postMapper.count(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(postMapper.paging(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Long countVo(PostQO qo) throws Exception {
    try {
      return postMapper.countVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public PostVO pkVo(PostQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return postMapper.pkVo(qo).setRoleList(postRoleMapper.getRoleListByPostId(qo.getId()));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Collection<PostVO> queryVo(PostQO qo) throws Exception {
    try {
      return postMapper.queryVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Paging<PostVO> pagingVo(Param<PostQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<PostVO> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = postMapper.countVo(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(postMapper.pagingVo(paging, null));
        }
      } else {
        Long count = postMapper.countVo(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(postMapper.pagingVo(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public CoreTree<?> getOrgPostTreeData(PostQO qo) throws Exception {
    try {
      CoreTree<?> tree = null;
      Collection<CoreTree<?>> treeSet = new ArrayList<>();
      Collection<Org> rOrgSet = orgMapper.query(new OrgQO().setWeightOrderAsc("y"));
      if (CoreTool.isNotEmpty(rOrgSet)) {
        CoreDataEvent coreDataEvent = new CoreDataEvent("getDictValueMapInfoByDictKey", "orgType");
        applicationEventPublisher.publishEvent(coreDataEvent);
        LinkedHashMap<String, String> dictValueMapInfo = CoreTool.isNotNullStr(coreDataEvent.getData()) ? coreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
        for (Org eo : rOrgSet) {
          treeSet.add(new CoreTree<Org>(eo, false, false, false, true)
              .setId(eo.getId())
              .setKey(eo.getId())
              .setName(eo.getOrgName())
              .setTkey(eo.getOrgType())
              .setTitle(eo.getOrgNameAbbr() + " - [" + dictValueMapInfo.get(eo.getOrgType()) + "]")
              .setValue(eo.getId())
              .setPid(eo.getPid()));
        }
      }
      Collection<Post> rPostSet = postMapper.query(new PostQO().setWeightOrderAsc("y"));
      if (CoreTool.isNotEmpty(rPostSet)) {
        if (CoreTool.isNullEo(qo)) {
          for (Post eo : rPostSet) {
            treeSet.add(new CoreTree<Post>(eo)
                .setId(eo.getId())
                .setKey(eo.getId())
                .setName(eo.getPostName())
                .setTkey("post")
                .setTitle(eo.getPostName() + " - [岗位]")
                .setValue(eo.getId())
                .setPid(eo.getFkid()));
          }
        } else {
          if (CoreTool.isNotEmpty(qo.getPostList())) {
            LinkedHashMap<String, String> postListMapInfo = new LinkedHashMap<>();
            for (String str : qo.getPostList()) {
              postListMapInfo.put(str, str);
            }
            for (Post eo : rPostSet) {
              treeSet.add(new CoreTree<Post>(eo, false, false, false, postListMapInfo.containsKey(eo.getId()) ? false : true)
                  .setId(eo.getId())
                  .setKey(eo.getId())
                  .setName(eo.getPostName())
                  .setTkey("post")
                  .setTitle(eo.getPostName() + " - [岗位]")
                  .setValue(eo.getId())
                  .setPid(eo.getFkid()));
            }
          } else {
            for (Post eo : rPostSet) {
              treeSet.add(new CoreTree<Post>(eo, false, false, false, true)
                  .setId(eo.getId())
                  .setKey(eo.getId())
                  .setName(eo.getPostName())
                  .setTkey("post")
                  .setTitle(eo.getPostName() + " - [岗位]")
                  .setValue(eo.getId())
                  .setPid(eo.getFkid()));
            }
          }
        }
      }
      tree = CoreTool.toTree(treeSet, true);
      return tree;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

}
